﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LAB.Manager
{
    public static class VideoManager
    {
        public delegate void handler(t_video video);

        public static event handler afterInsert;
        public static event handler afterDelete;
        public static event handler afterEdit;

        public delegate void tagHandler(int videoId, List<int> tagIds);

        public static event tagHandler afterAddTags;
        public static event tagHandler afterRemoveTags;

        /*
            t_video
            视频
            id
            name		视频名称
            dt		创建时间
            status		状态
            count		访问次数
            editor		创建者
            url		视频地址
         */

        public static bool insertWithTagIds(string name, string url, List<int> tagIds, string editor)
        {
            bool rst = false;
            t_video video = insert(name, url, editor);
            if (video != null)
            {
                rst = addTags(video.id, tagIds, editor);
                if (rst)
                {
                    // trigger
                    if (afterInsert != null)
                    {
                        afterInsert(video);
                    }
                }
            }
            return rst;
        }

        static t_video insert(string name, string url, string editor)
        {
            t_video rst = null;
            using (var db = new TagerEntities())
            {
                if (db.t_video.Count(c => c.name == name || c.url == url) >= 1)
                {
                    return null;
                }
                var video = new t_video { count = 0, dt = DateTime.Now, editor = editor, name = name, status = 0, url = url };
                db.t_video.Add(video);
                db.SaveChanges();
                rst = video;

            }
            return rst;
        }

        public static bool edit(int id, string name, List<int> tagIds, string url, int status, string editor)
        {
            var rst = false;
            using (var db = new TagerEntities())
            {
                var video = db.t_video.FirstOrDefault(c => c.id == id);
                if (video == null)
                {
                    return false;
                }

                // 补充一点 
                // 新改的name和url不能喝其他的video相同

                if (db.t_video.Count(c => c.name == name && c.url == url && c.id != id) == 0)
                {
                    video.name = name;
                    video.url = url;
                    video.status = status;
                    db.SaveChanges();
                    var videoTags = db.t_videoTag.Where(c => c.videoId == video.id).Select(c => c.tagId);
                    var tagIdsForRemove = videoTags.Except(tagIds).ToList();
                    var tagIdsForAdd = tagIds.Except(videoTags).ToList();
                    removeTags(video.id, tagIdsForRemove, editor);
                    addTags(video.id, tagIdsForAdd, editor);
                    rst = true;
                    // trigger
                    if (afterEdit != null) { afterEdit(video); }
                }
            }

            return rst;
        }



        public static bool delete(int id, string editor)
        {
            var rst = false;
            using (var db = new TagerEntities())
            {
                var video = db.t_video.FirstOrDefault(c => c.id == id);
                if (video == null)
                {
                    return false;
                }
                if (video.editor == editor || SysUtil.isSysEditor(editor))
                {
                    db.t_video.Remove(video);
                    db.SaveChanges();
                    // trigger
                    if (afterDelete != null)
                    {
                        afterDelete(video);
                    }
                }
            }
            return rst;
        }

        public static List<fullVideo> search(List<int> tagIds, int status, int pageIndex, int pageSize, out int total)
        {
            List<fullVideo> rst = null;
            List<t_video> videos = null;
            total = 0;
            using (var db = new TagerEntities())
            {
                IEnumerable<t_video> list = db.t_video.Where(c => c.status == status);
                if (tagIds != null)
                {
                    var groups = db.t_videoTag.GroupBy(c => c.videoId);
                    groups = groups.Where(c => tagIds.All(d => c.Any(cc => cc.tagId == d)));
                    list = list.Where(c => groups.Any(d => d.Key == c.id));

                }
                total = list.Count();
                videos = list.Skip(pageIndex * pageSize).Take(pageSize).ToList();

                rst = videos.Select(c => new fullVideo() { video = c, tags = TagManager.searchByVideoId(c.id) }).ToList();

            }
            return rst;
        }

        public static List<t_video> getHotVideo(int count)
        {
            List<t_video> rst = null;
            using (var db = new TagerEntities())
            {
                IEnumerable<t_video> list = db.t_video.Where(c => c.status == 1);

                rst = list.OrderBy(c => c.count).Take(count).ToList();
            }
            return rst;
        }

        // video's  tags

        public static bool addTags(int videoId, List<int> tagIds, string editor)
        {
            var rst = false;
            using (var db = new TagerEntities())
            {
                var video = db.t_video.FirstOrDefault(c => c.id == videoId);
                if (video == null)
                {
                    return false;
                }
                if (video.editor == editor || SysUtil.isSysEditor(editor))
                {
                    // 1 tagId必须是存在的tag
                    // 2 tagId必须是现有的videoTags中不存在的 
                    //tagIds = tagIds.Where(c => db.t_tag.Any(d => d.id == c)).
                    //    Where(c => db.t_videoTag.Where(d => d.videoId == videoId).All(d => d.tagId != c))
                    //    .ToList();
                    var videoTagIds = db.t_videoTag.Where(c => c.videoId == videoId).Select(c => c.tagId).ToList();
                    tagIds = tagIds.Except(videoTagIds).ToList();
                    foreach (var ti in tagIds)
                    {
                        db.t_videoTag.Add(new t_videoTag { videoId = videoId, tagId = ti, dt = DateTime.Now });
                    }
                    db.SaveChanges();
                    rst = true;
                    // trigger
                    if (afterAddTags != null)
                    {
                        afterAddTags(videoId, tagIds);
                    }
                }
            }
            return rst;
        }

        public static bool removeTags(int videoId, List<int> tagIds, string editor)
        {
            var rst = false;
            using (var db = new TagerEntities())
            {
                var video = db.t_video.FirstOrDefault(c => c.id == videoId);
                if (video == null)
                {
                    return false;
                }

                if (video.editor == editor || SysUtil.isSysEditor(editor))
                {
                    var videoTags = db.t_videoTag.Where(c => c.videoId == videoId && tagIds.Contains(c.tagId));
                    foreach (var vti in videoTags)
                    {
                        db.t_videoTag.Remove(vti);
                    }

                    db.SaveChanges();
                    rst = true;
                    // trigger
                    if (afterRemoveTags != null)
                    {
                        afterRemoveTags(videoId, videoTags.Select(c => c.tagId).ToList());
                    }
                }
            }
            return rst;

        }






    }
}
